//
/*   Helper code for Matrix * Vector operation program
*    Copyright (C) 2009 Goffredo Marocchi
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "MatTest_helper.h"
#include "msglib.h"
#include "errlib.h"

////////////////////////////////////////////////
// General Purpose Functions
////////////////////////////////////////////////

/**\brief This tests if two vectors are equal or not
 *
 * Both vectors must have the same length.\n
 *
 * \param a first vector, float*
 * \param b second vector, float*
 *
 * \param SIZE length of both vectors, const int
 *
 * \return bool
 */
bool vectorEQ (float* a, float* b, const int SIZE) {

	if (null == a || null == b) return false;

	for (int i = 0; i < SIZE; i++) {

		if ( a[i] != b[i] ) {

			send_msg ("\nIndex: %d\n", i);
			send_msg ("a[%d]: %f , b[%d]: %f\n", i, a[i], i, b[i]);
			return false;

		}

	}

	return true;
}

/**\brief This tests if two vectors are equal or not
 *
 * Both vectors must have the same length.\n
 *
 * \param a first vector, float*
 * \param b second vector, float*
 *
 * \param SIZE length of both vectors, const int
 *
 * \return void
 */
extern "C" void vector_eq_test_ (float* a, float* b, const int SIZE) {

	bool test = true;

	if (null == a || null == b) test = false;

	for (int i = 0; i < SIZE; i++) {

		if ( a[i] != b[i] ) {

			err_msg ("\nIndex: %d\n", i);
			err_msg ("a[%d]: %f , b[%d]: %f\n", i, a[i], i, b[i]);
			test = false;

		}

	}

	if ( false == test ) {

		err_msg("\n(ERR) The two vectors are not equal :(.\n");

	}

	else {

		send_msg("\n(OK) The two vectors are equal :).\n");

	}

	return;
}


/**\brief This function calculates a random floating point number (single precision)
 *
 * \param low minimum value of the chosen interval, float
 * \param high maximum value of the chosen interval, float
 * \return float
 */
float RandFloat(float low, float high){
	float t = (float)rand() / (float)RAND_MAX;
	return (1.0f - t) * low + t * high;
}

/**\brief This function dynamically allocates a matrix
 * More convoluted method, but the final matrix can be nicely used as a fully working 2D array (mat[][]).
 *
 * \param mat the pointer to pointer to pointer variable is used to store the matrix, float***
 * \return void
 */
void malloc_MatrixFPv1 ( float*** mat, const int rows, const int columns) {

	int i,index;

	(*mat) = (float **) calloc (rows, sizeof(float *)); //calloc does the same thing as malloc but
	//inits memory to 0

	*(*mat) = (float *) calloc (rows * columns, sizeof (float));

	for (i = 0; i < rows; i++) {

		for (index = 0; ; index = 0 + i*columns) {

			*((*mat) + i) = ((**mat) + index);

		}

	}

	return;

}


/**\brief This function dynamically allocates a matrix
 *
 * Se adoperiamo questa v2 della funzione che alloca una matrice dinamicamente allora\n
 * useremo in seguito per accedere alla matrice, implementata con un largo array 1D, la seguente macro:\n
 * \n
 * 	index(i, j , n_columns) ((j) + ((i) * (n_columns))) //row-major matrix\n
 * \n
 * gia' definita in precedenza.\n
 *
 * \param mat pointer to pointer variable used to store the matrix, float**
 * \param rows number of rows of the matrix, const int
 * \param columns number of columns of the matrix, const int
 * \return void
 */
void malloc_matrixFPv2 ( float** mat, const int rows, const int columns) {

	(*mat) = (float *) calloc (rows * columns, sizeof (float)); //calloc sets the allocated memory to 0...

	return;

}

